/**********************************************
 * Program: Scroll                            *
 *                                            *
 * Displays text files like the type command, *
 * but additionally can scroll backwards.     *
 **********************************************/

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "list.h"

/*************
 * constants *
 *************/

#define PAGE 24
#define LINEWIDTH 75
#define MAXLINE 10000

/***********
 * globals *
 ***********/

int topline;

/*************
 * functions *
 *************/

/* read a text file into a list of lines */
int ReadFile (List *l,char *file)
{
   FILE *f;
   int len;
   int i,done;
   char line[MAXLINE];

   done = 0;
   f = fopen(file,"rt");

   if (f) {
      while (!feof(f)) {
         /* read next line */
         fgets(line,MAXLINE,f);
         len = strlen(line);
         if (len > 0) {
            if (line[len-1] == '\n')
               line[len-1] = 0;

            /* eliminate special characters */
            for (i=0;i<len;i++)
               if (line[i]<' ')
                  line[i]=' ';

            line[LINEWIDTH] = 0;
            ListAdd(l,line,LINEWIDTH+1);
         }
      }
      fclose(f);
      done = 1;
   }
   return done;
}

/* show next screen */
void ShowPage (List list)
{
   int n,done;

   printf("\n");
   done = 1;

   for (n = 0; n < PAGE; n++)
      if (done) {
         printf("%3d: %-75s",topline+n,ListGetData(list));
         done = ListNext(&list);
      }
      else
         printf("\n");
   printf("<<n=next page, p=previous page, q=quit>> ");
}

/* user interface */
void ScrollFile (List list)
{
   int c,n;

   topline = 1;
   ShowPage (list);

   do {
      c = getchar();
      switch (toupper(c)) {
         case 'N': for (n = 0; n < PAGE; n++)
                      if (ListNext(&list))
                         topline++;
                   ShowPage (list);
                   break;
         case 'P': for (n = 0; n < PAGE; n++)
                      if (ListPrev(&list))
                         topline--;
                   ShowPage(list);
                   break;
         case 'Q': c = EOF;
                   break;
      }
   } while (c != EOF);
}

/****************
 * main program *
 ****************/

int main (int argc, char **argv)
{
   List list;
   char fname[100];
   
   switch (argc) {
   case 1: printf("enter name of file to scroll: ");
           gets(fname); 
           break;
   case 2: strcpy(fname,argv[1]); 
           break;
   default: *fname=0;
   }
   
   if (*fname) {
      list = NULL;

      if (ReadFile (&list,fname))
         ScrollFile (list);
      else
         printf("cannot open file: %s!\n",fname);

      ListFree (list);
   }
   else
      printf("Usage: scroll <file>\n");
   return 0;
}
